#pragma once
#include <iostream>
#include <string>
#include <vector>
#include<functional>
#include "InetAddr.hpp"
#include"ThreadPool.hpp"

using task_t = function<void()>;
class Route
{
public:
    Route(){
        pthread_mutex_init(&_mutex, nullptr);
    }
    bool CheckOnlineUsr(InetAddr &who)
    {
        LockGuard t(&_mutex);
        for (auto &usr : _online_usr)
        {
            if (usr == who)
                return true;
        }
        return false;
    }
    void OffLine(InetAddr &who)
    {
        LockGuard t(&_mutex);
        auto it = _online_usr.begin();
        for (; it != _online_usr.end();it++)
        {
            if(*it==who)
            {
                _online_usr.erase(it);
                break;
            }
        }
    }
    void ForwardHelper(int sockfd,const string messages)
    {
        for(auto &usr:_online_usr)
        {           
            struct sockaddr_in peer = usr.Addr();
            int n=sendto(sockfd, messages.c_str(), messages.size(), 0, (struct sockaddr *)&peer,sizeof(peer));
            if(n>0) LOG(DEBUG, "send ok\n");
        }
    }

    void Forward(int sockfd, const string &msg, InetAddr &who)
    {
        // 检查是否在用户列表
        if(!CheckOnlineUsr(who))
        {
            _online_usr.push_back(who);
            LOG(DEBUG, "addusr\n");
        }
        if(msg=="QUIT"||msg=="Q")
        {
            OffLine(who);
        }
        string messages='['+who.Ip()+":"+to_string(who.Port())+"]:"+msg;
        task_t t = bind(&Route::ForwardHelper, this, sockfd, messages);
        ThreadPool<task_t>::GetThreadPool()->Enqueue(t);
        LOG(DEBUG, "ok\n");
    }
    ~Route() {
        pthread_mutex_destroy(&_mutex);
    }

private:
    vector<InetAddr> _online_usr;
    pthread_mutex_t _mutex;
};